Docly Developers
Knowledge base Clarification By design

Path traversal

In shortDocly's filesystem functions reject ".." and "\", so classic ../ traversal cannot escape a folder. But every path is absolute from the site root and can reach any file in the site — including the private files under #/, such as #/Config with its secrets. Never pass user input as a whole path: build the path from a fixed folder and a validated name.
Applies to API scriptsSecurity
  1. What you'll see

    AI code-review tools flag path traversal when Docly's filesystem functions (getFile, getJson, getFiles, getFolder, fileExists …) are called with paths derived from user input. Some of that advice is beside the point in Docly, and some of it is exactly right.
  2. What's actually happening

    What Docly blocks. The filesystem functions reject any path containing .. or a backslash, and every path is absolute from the site root — there is no current directory. A payload like ../../secret is refused, not resolved, so it cannot climb out of a folder.

    What it does not block. An absolute path can name any file in the site. That includes everything under #/: #/Config, #/Services/oauth.json, your API scripts. The #/ folder is not served to visitors, but a script that reads a path the visitor chose will read it for them.

    // #/API/doc.js — DANGEROUS: the caller picks any file in the site
    export default (path) => docly.getJson(path);
    // /API/doc?path=%23/Config  → returns your secrets

    So the risk is not traversal but an unrestricted path: user input used as the whole path, or as a path with its own slashes.

  3. What to do

    Build the path yourself from a fixed folder and a name, and validate the name before you use it:

    // #/API/product.js
    export default (id) => {
        if (!docly.validateFilename(id)) return { error: "Invalid id" };   // rejects /, \, "." and ".."
        return docly.getJson("/Products/" + id);
    };
    • Never pass user input as the whole path, and never let it contain /. docly.validateFilename rejects slashes, backslashes, . and ...
    • Where the set of valid values is known, check against an allowlist.
    • Reading is not the end of it: check that the caller may see the document you found — see Check access on the document you write.
    • Keep secrets under #/ anyway — it keeps them out of the published site — but do not rely on that alone when a script takes a path from the request.

    When an AI tool reports classic ../ traversal, the .. part is handled by the platform. Check instead whether the input can choose the whole path.

Last reviewed 22 Oct 2026